package abacab.actor.queue;

import java.util.Queue;

import abacab.ActorSystem;
import abacab.message.Envelope;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigException.BadValue;

/**
 * The handler for queues management
 */
public class QueueHandler {
	/**
	 * Get the queue to use for messages storing
	 * 
	 * @param system
	 *          the actor system
	 * @param queueName
	 *          the queue's name
	 * @return the queue to use
	 * @throws ConfigException
	 *           if the configuration is invalid
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Queue<Envelope> getQueue(ActorSystem system, String queueName) throws ConfigException {
		if (queueName == null) {
			queueName = "default";
		}
		Config queueConfig;
		try {
			queueConfig = system.getConfig().getConfig("abacab.queues." + queueName);
		}
		catch (ConfigException e) {
			throw new ConfigException.NotResolved("The queue \"" + queueName + "\" was not found", e);
		}

		// Get the factory
		String factory = queueConfig.getString("factory");
		Class<QueueFactory> queueClass;
		try {
			queueClass = (Class<QueueFactory>) Class.forName(factory);
		}
		catch (ClassNotFoundException e) {
			throw new BadValue("abacab.queues." + queueName + ".factory", "The queue's factory \"" + factory
					+ "\" does not exist", e);
		}
		catch (ClassCastException e) {
			throw new BadValue("abacab.queues." + queueName + ".factory", "The queue's factory \"" + factory
					+ "\" does not implement \"" + QueueFactory.class.getName() + "\"");
		}

		// Build the factory
		QueueFactory queueFactory;
		try {
			queueFactory = queueClass.newInstance();
		}
		catch (Exception e) {
			throw new BadValue("abacab.queues." + queueName + ".factory", "The queue's factory \"" + factory
					+ "\" can not be built", e);
		}

		return queueFactory.buildQueue(queueConfig);
	}
}